I am almost certain I am hitting some kind of bug. All of a sudden, array()=
=20
stops returning an empty array and starts returning something weird. The we=
ird=20
thing behaves as NULL in most circumstances (e.g. gettype() says NULL),=20
except:
$foo=3Darray(); // <-- weird thing returned
$foo[]=3D"bar";
causes "Fatal error: [] operator not supported for strings", which is diffe=
rent=20
from the regular behavior of:
$foo=3Dnull;
$foo[]=3D"bar"; // <-- $foo simply becomes an array
The problem is not limited to one place in code, and indeed before the fata=
l=20
caused by append-assignment I get several warnings like "array_diff_key():=
=20
Argument #1 is not an array", where the offending argument receives a resul=
t of=20
array().
The effect is not random, i.e. it always breaks identically when the same=20
script processes the same data. However I was so far unable to create a=20
minimal test case that triggers the bug. My script is rather involved, and=
=20
here are some things it uses:
- Exceptions
- DOM to-fro SimpleXML
- lots of multi-level output buffering
Disabling Zend Optimizer doesn't help. Disabling Zend Memory Manager is=20
apparently impossible. Memory usage is below 10MB out of 128MB limit.
Any similar experiences? Ideas what to check for? Workarounds?
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Re: array() returns something weird
am 22.08.2009 20:39:06 von Lars Torben Wilson
2009/8/22 Szczepan HoÅyszewski :
> Hello!
>
> I am almost certain I am hitting some kind of bug. All of a sudden, array=
()
> stops returning an empty array and starts returning something weird. The =
weird
> thing behaves as NULL in most circumstances (e.g. gettype() says NULL),
> except:
>
> Â Â Â Â $foo=3Darray(); Â Â Â // <-- wei=
rd thing returned
> Â Â Â Â $foo[]=3D"bar";
>
> causes "Fatal error: [] operator not supported for strings", which is dif=
ferent
> from the regular behavior of:
Hi there,
Without seeing the actual code, it's hard to say what the problem is.
However, I'd be pretty surprised if you've actually run into a bug in
PHP--I would first suspect a bug in your code. No offense
intended--that's just how it usually plays out. :)
What it looks like to me is that something is causing $foo to be a
string before the '$foo[] =3D "bar";' line is encountered. What do you
get if you put a gettype($foo); just before that line?
> Â Â Â Â $foo=3Dnull;
> Â Â Â Â $foo[]=3D"bar"; Â Â Â // <-- $fo=
o simply becomes an array
>
> The problem is not limited to one place in code, and indeed before the fa=
tal
> caused by append-assignment I get several warnings like "array_diff_key()=
:
> Argument #1 is not an array", where the offending argument receives a res=
ult of
> array().
This would appear to support my suspicion, but try inserting the
gettype($foo) (or better, var_export($foo);) just before one of the
lines which triggers the error, and post the results.
Can you post the code in a .zip file or online somewhere? If not,
that's cool, but it will probably make it harder to help you track it
down if you can't.
Regards,
Torben
> The effect is not random, i.e. it always breaks identically when the same
> script processes the same data. However I was so far unable to create a
> minimal test case that triggers the bug. My script is rather involved, an=
d
> here are some things it uses:
>
> Â - Exceptions
> Â - DOM to-fro SimpleXML
> Â - lots of multi-level output buffering
>
> Disabling Zend Optimizer doesn't help. Disabling Zend Memory Manager is
> apparently impossible. Memory usage is below 10MB out of 128MB limit.
>
> Any similar experiences? Ideas what to check for? Workarounds?
>
> From phpinfo():
>
> PHP Version:
> 5.2.9 (can't easily upgrade - shared host)
>
> System:
> FreeBSD 7.1-RELEASE-p4 FreeBSD 7.1-RELEASE-p4 #0: Wed Apr 15 15:48:43 UTC=
2009
> amd64
>
> Configure Command:
> './configure' '--enable-bcmath' '--enable-calendar' '--enable-dbase' '--e=
nable-
> exif' '--enable-fastcgi' '--enable-force-cgi-redirect' '--enable-ftp' '--
> enable-gd-native-ttf' '--enable-libxml' '--enable-magic-quotes' '--enable=
-
> maintainer-zts' '--enable-mbstring' '--enable-pdo=3Dshared' '--enable-saf=
e-mode'
> '--enable-soap' '--enable-sockets' '--enable-ucd-snmp-hack' '--enable-wdd=
x'
> '--enable-zend-multibyte' '--enable-zip' '--prefix=3D/usr' '--with-bz2' '=
--with-
> curl=3D/opt/curlssl/' '--with-curlwrappers' '--with-freetype-dir=3D/usr/l=
ocal' '--
> with-gd' '--with-gettext' '--with-imap=3D/opt/php_with_imap_client/' '--w=
ith-
> imap-ssl=3D/usr/local' '--with-jpeg-dir=3D/usr/local' '--with-libexpat-
> dir=3D/usr/local' '--with-libxml-dir=3D/opt/xml2' '--with-libxml-dir=3D/o=
pt/xml2/'
> '--with-mcrypt=3D/opt/libmcrypt/' '--with-mhash=3D/opt/mhash/' '--with-mi=
me-magic'
> '--with-mysql=3D/usr/local' '--with-mysql-sock=3D/tmp/mysql.sock' '--with=
-
> mysqli=3D/usr/local/bin/mysql_config' '--with-openssl=3D/usr/local' '--wi=
th-
> openssl-dir=3D/usr/local' '--with-pdo-mysql=3Dshared' '--with-pdo-sqlite=
=3Dshared'
> '--with-pgsql=3D/usr/local' '--with-pic' '--with-png-dir=3D/usr/local' '-=
-with-
> pspell' '--with-snmp' '--with-sqlite=3Dshared' '--with-tidy=3D/opt/tidy/'=
'--with-
> ttf' '--with-xmlrpc' '--with-xpm-dir=3D/usr/local' '--with-xsl=3D/opt/xsl=
t/' '--
> with-zlib' '--with-zlib-dir=3D/usr'
>
> Thanks in advance,
> Szczepan Holyszewski
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Re: array() returns something weird
am 22.08.2009 21:52:55 von webmaster
> What it looks like to me is that something is causing $foo to be a
> string before the '$foo[] = "bar";' line is encountered. What do you
> get if you put a gettype($foo); just before that line?
>
> > $foo=null;
> > $foo[]="bar"; // <-- $foo simply becomes an array
NULL. That is the problem. I _did_ put a gettype($foo) before the actual line.
OK, here are exact four lines of my code:
$ret=array();
foreach(self::$_allowed as $r => $a)
if ($a)
$ret[]=$r;
As you can see, there is not a shred of a chance for $ret to become something
other than empty array between initialization and the last line in the above
snippet which causes the fatal errror. There's no __staticGet in 5.2.9, so
self::$_allowed cannot have side effects.
Secondly, the above code starts failing after it has executed successfully
dozens of times (and yes, the last line _does_ get executed; in fact self::
$_allowed contains configuration information that doesn't change at runtime).
Thirdly...
> > The problem is not limited to one place in code, and indeed before the
> > fatal caused by append-assignment I get several warnings like
> > "array_diff_key(): Argument #1 is not an array", where the offending
> > argument receives a result of array().
>
> This would appear to support my suspicion, but try inserting the
> gettype($foo) (or better, var_export($foo);) just before one of the
> lines which triggers the error, and post the results.
No, I don't think it supports your suspicion. Conversely, it indicates that
once array() returns a strangelet, it starts returning strangelets all over
the place. Initially it only triggers warnings but eventually one of the
returned strangelets is used in a way that triggers a fatal error.
As per your request:
//at the beginning of the script:
$GLOBALS['offending_line_execution_count']=0;
// /srv/home/[munged]/public_html/scripts/common.php line 161 and on
// instrumented as per your request:
public static function GetAllowed() {
if (debug_mode()) echo ++$GLOBALS['offending_line_execution_count']." ";
$ret=array();
if (debug_mode()) echo var_export($ret)." ";
foreach(self::$_allowed as $r => $a)
if ($a)
$ret[]=$r;
Warning: array_diff_key() [function.array-diff-key]: Argument #1 is not an array
in /srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 350
Warning: Invalid argument supplied for foreach() in
/srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 351
Warning: array_merge() [function.array-merge]: Argument #2 is not an array in
/srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 357
Warning: Invalid argument supplied for foreach() in
/srv/home/u80959ue/public_html/scripts/common.php on line 28
Warning: Invalid argument supplied for foreach() in
/srv/home/u80959ue/public_html/scripts/common.php on line 28
Warning: Invalid argument supplied for foreach() in
/srv/home/u80959ue/public_html/scripts/common.php on line 28
33
NULL
Fatal error: [] operator not supported for strings in
/srv/home/u80959ue/public_html/scripts/common.php on line 168
--------------------------------------------------
The warnings come from other uses of array().
But wait! There is this invocation of debug_mode() between initialization of
$ret var_export. Let's factor it out to be safe:
$debugmode=debug_mode();
if ($debugmode) echo ++$GLOBALS['offending_line_execution_count']." ";
$ret=array();
if ($debugmode) echo var_export($ret)." ";
And now the output ends with:
------------------------------------
Warning: Invalid argument supplied for foreach() in
/srv/home/u80959ue/public_html/scripts/common.php on line 28
33
Fatal error: [] operator not supported for strings in
/srv/home/u80959ue/public_html/scripts/common.php on line 169
------------------------------------
No NULL after 33? What the heck is going on? Does array() now return something
that var_exports to an empty string, or does it destroy local variables? Let's
see:
if ($debugmode) echo var_export($ret)." "; else echo "WTF?!?!? ";
And the output:
------------------------------------
Warning: Invalid argument supplied for foreach() in
/srv/home/u80959ue/public_html/scripts/common.php on line 28
33
WTF?!?!?
Fatal error: [] operator not supported for strings in
/srv/home/u80959ue/public_html/scripts/common.php on line 169
---------------------------------------
Indeed, the use of array(), once it starts misbehaving, wreaks havoc in the
local scope (possibly including the variable to which its result is assigned).
> Can you post the code in a .zip file or online somewhere?
Unfortunately not.
Szczepan Holyszewski
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Re: array() returns something weird
am 22.08.2009 23:08:10 von Lars Torben Wilson
2009/8/22 Szczepan HoÅyszewski :
>> What it looks like to me is that something is causing $foo to be a
>> string before the '$foo[] =3D "bar";' line is encountered. What do you
>> get if you put a gettype($foo); just before that line?
>>
>> > Â Â Â Â $foo=3Dnull;
>> > Â Â Â Â $foo[]=3D"bar"; Â Â Â // <-- =
$foo simply becomes an array
>
> NULL. That is the problem. I _did_ put a gettype($foo) before the actual =
line.
>
> OK, here are exact four lines of my code:
>
> Â Â Â Â $ret=3Darray();
> Â Â Â Â foreach(self::$_allowed as $r =3D> $a)
> Â Â Â Â Â Â Â Â if ($a)
> Â Â Â Â Â Â Â Â Â Â =C2=
=A0 Â $ret[]=3D$r;
>
> As you can see, there is not a shred of a chance for $ret to become somet=
hing
> other than empty array between initialization and the last line in the ab=
ove
> snippet which causes the fatal errror. There's no __staticGet in 5.2.9, s=
o
> self::$_allowed cannot have side effects.
>
> Secondly, the above code starts failing after it has executed successfull=
y
> dozens of times (and yes, the last line _does_ get executed; in fact self=
::
> $_allowed contains configuration information that doesn't change at runti=
me).
>
> Thirdly...
>
>> > The problem is not limited to one place in code, and indeed before the
>> > fatal caused by append-assignment I get several warnings like
>> > "array_diff_key(): Argument #1 is not an array", where the offending
>> > argument receives a result of array().
>>
>> This would appear to support my suspicion, but try inserting the
>> gettype($foo) (or better, var_export($foo);) just before one of the
>> lines which triggers the error, and post the results.
>
> No, I don't think it supports your suspicion. Conversely, it indicates th=
at
> once array() returns a strangelet, it starts returning strangelets all ov=
er
> the place. Initially it only triggers warnings but eventually one of the
> returned strangelets is used in a way that triggers a fatal error.
>
> As per your request:
>
> Â Â Â Â //at the beginning of the script:
>
> Â Â Â Â $GLOBALS['offending_line_execution_count']=3D0=
;
>
> Â Â Â Â // /srv/home/[munged]/public_html/scripts/comm=
on.php line 161 and on
> Â Â Â Â // instrumented as per your request:
>
> Â Â Â Â public static function GetAllowed() {
>
> Â Â Â Â Â Â Â Â if (debug_mode()) =
echo ++$GLOBALS['offending_line_execution_count']." ";
> Â Â Â Â Â Â Â Â $ret=3Darray();
> Â Â Â Â Â Â Â Â if (debug_mode()) =
echo var_export($ret)." ";
> Â Â Â Â Â Â Â Â foreach(self::$_al=
lowed as $r =3D> $a)
> Â Â Â Â Â Â Â Â Â Â =C2=
=A0 Â if ($a)
> Â Â Â Â Â Â Â Â Â Â =C2=
=A0 Â Â Â Â Â $ret[]=3D$r;
>
> Â Â Â Â Â Â Â Â if (self::$_allowE=
mpty) $ret[]=3D"";
> Â Â Â Â Â Â Â Â return $ret;
> Â Â Â Â }
>
> Output tail:
> -----------------------------------------------
> 28
> array ( )
> 29
> array ( )
> 30
> array ( )
> 31
> array ( )
> 32
> array ( )
>
> Warning: array_diff_key() [function.array-diff-key]: Argument #1 is not a=
n array
> in /srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 350
>
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 351
>
> Warning: array_merge() [function.array-merge]: Argument #2 is not an arra=
y in
> /srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 357
>
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
>
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
>
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
> 33
> NULL
>
> Fatal error: [] operator not supported for strings in
> /srv/home/u80959ue/public_html/scripts/common.php on line 168
> --------------------------------------------------
>
> The warnings come from other uses of array().
>
> But wait! There is this invocation of debug_mode() between initialization=
of
> $ret var_export. Let's factor it out to be safe:
>
> Â Â Â Â Â Â Â Â $debugmode=3Ddebug=
_mode();
> Â Â Â Â Â Â Â Â if ($debugmode) ec=
ho ++$GLOBALS['offending_line_execution_count']." ";
> Â Â Â Â Â Â Â Â $ret=3Darray();
> Â Â Â Â Â Â Â Â if ($debugmode) ec=
ho var_export($ret)." ";
>
> And now the output ends with:
>
> ------------------------------------
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
> 33
>
> Fatal error: [] operator not supported for strings in
> /srv/home/u80959ue/public_html/scripts/common.php on line 169
> ------------------------------------
>
> No NULL after 33? What the heck is going on? Does array() now return some=
thing
> that var_exports to an empty string, or does it destroy local variables? =
Let's
> see:
>
> Â Â Â Â Â Â Â Â if ($debugmode) ec=
ho var_export($ret)." "; else echo "WTF?!?!? ";
>
> And the output:
> ------------------------------------
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
> 33
> WTF?!?!?
>
> Fatal error: [] operator not supported for strings in
> /srv/home/u80959ue/public_html/scripts/common.php on line 169
> ---------------------------------------
>
> Indeed, the use of array(), once it starts misbehaving, wreaks havoc in t=
he
> local scope (possibly including the variable to which its result is assig=
ned).
>
>> Can you post the code in a .zip file or online somewhere?
>
> Unfortunately not.
>
> Szczepan Holyszewski
Hm. . .it does look odd. Searching the bugs database at
http://bugs.php.net does turn up one other report (at
http://bugs.php.net/bug.php?id=3D47870 ) of array() returning NULL in
certain hard-to-duplicate circumstances on FreeBSD, although it's a
different version of FreeBSD and is reported against
5.3CVS-2009-04-01. There are differences but the similarities are
suspicious. That particular bug was fixed but if this does in fact
turn out to be a bug in PHP then the ability to test other versions
would be very useful. Too bad about the shared host. I know how hard
it can be to get them to install other versions, even if just for
testing.
I don't suppose you have a development environment on another machine
where you can test another version of PHP? If not, it's going to be
slightly difficult to pin down.
It may be worth it for you to add a comment to the above bug report.
The current 5.2 is only at 5.2.10 so the version you're using isn't
very old, and a fix for this problem is not specifically mentioned in
the PHP 5.2.10 changelog.
Good luck!
Torben
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Re: array() returns something weird
am 22.08.2009 23:48:50 von Ralph Deffke
well, when I saw ur post I got immediately the thought I would bed it has to
do with some stuff of $this or self.
I did play arround a bit with class creation the last days and yes, with
using self parent and $this I did put the HTTPPD in unstable and sometimes
it died without beeing able to send any error.
well this doesn't help very mutch.
I have two point:
(1)ur code is ( sorry ) lazy written, invest the brackets !! ur code writing
is predestinated for that type of error. shooting variable types arround by
pulling out of foreach loops, if's, .... is typical.
(2) using static variables are known for type missmatch errors just anything
has acces to them even if the containing class is not instantinated. many
dirty things can happen unless of corse they are not private.
further sugestions: check if you work on ur arrays with functions returning
array on success but false on fail or something like that. also a typical
source for that type of error
are u using magic __set ? I ran into a type change as well with it
good luck
ralph_deffke@yahoo.de
"Szczepan Holyszewski" wrote in message
news:200908222152.55846.webmaster@strefarytmu.pl...
> > What it looks like to me is that something is causing $foo to be a
> > string before the '$foo[] = "bar";' line is encountered. What do you
> > get if you put a gettype($foo); just before that line?
> >
> > > $foo=null;
> > > $foo[]="bar"; // <-- $foo simply becomes an array
>
> NULL. That is the problem. I _did_ put a gettype($foo) before the actual
line.
>
> OK, here are exact four lines of my code:
>
> $ret=array();
> foreach(self::$_allowed as $r => $a)
> if ($a)
> $ret[]=$r;
>
> As you can see, there is not a shred of a chance for $ret to become
something
> other than empty array between initialization and the last line in the
above
> snippet which causes the fatal errror. There's no __staticGet in 5.2.9, so
> self::$_allowed cannot have side effects.
>
> Secondly, the above code starts failing after it has executed successfully
> dozens of times (and yes, the last line _does_ get executed; in fact
self::
> $_allowed contains configuration information that doesn't change at
runtime).
>
> Thirdly...
>
> > > The problem is not limited to one place in code, and indeed before the
> > > fatal caused by append-assignment I get several warnings like
> > > "array_diff_key(): Argument #1 is not an array", where the offending
> > > argument receives a result of array().
> >
> > This would appear to support my suspicion, but try inserting the
> > gettype($foo) (or better, var_export($foo);) just before one of the
> > lines which triggers the error, and post the results.
>
> No, I don't think it supports your suspicion. Conversely, it indicates
that
> once array() returns a strangelet, it starts returning strangelets all
over
> the place. Initially it only triggers warnings but eventually one of the
> returned strangelets is used in a way that triggers a fatal error.
>
> As per your request:
>
> //at the beginning of the script:
>
> $GLOBALS['offending_line_execution_count']=0;
>
> // /srv/home/[munged]/public_html/scripts/common.php line 161 and on
> // instrumented as per your request:
>
> public static function GetAllowed() {
>
> if (debug_mode()) echo
++$GLOBALS['offending_line_execution_count']." ";
> $ret=array();
> if (debug_mode()) echo var_export($ret)." ";
> foreach(self::$_allowed as $r => $a)
> if ($a)
> $ret[]=$r;
>
> if (self::$_allowEmpty) $ret[]="";
> return $ret;
> }
>
> Output tail:
> -----------------------------------------------
> 28
> array ( )
> 29
> array ( )
> 30
> array ( )
> 31
> array ( )
> 32
> array ( )
>
> Warning: array_diff_key() [function.array-diff-key]: Argument #1 is not an
array
> in /srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 350
>
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 351
>
> Warning: array_merge() [function.array-merge]: Argument #2 is not an array
in
> /srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 357
>
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
>
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
>
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
> 33
> NULL
>
> Fatal error: [] operator not supported for strings in
> /srv/home/u80959ue/public_html/scripts/common.php on line 168
> --------------------------------------------------
>
> The warnings come from other uses of array().
>
> But wait! There is this invocation of debug_mode() between initialization
of
> $ret var_export. Let's factor it out to be safe:
>
> $debugmode=debug_mode();
> if ($debugmode) echo ++$GLOBALS['offending_line_execution_count']." ";
> $ret=array();
> if ($debugmode) echo var_export($ret)." ";
>
> And now the output ends with:
>
> ------------------------------------
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
> 33
>
> Fatal error: [] operator not supported for strings in
> /srv/home/u80959ue/public_html/scripts/common.php on line 169
> ------------------------------------
>
> No NULL after 33? What the heck is going on? Does array() now return
something
> that var_exports to an empty string, or does it destroy local variables?
Let's
> see:
>
> if ($debugmode) echo var_export($ret)." "; else echo "WTF?!?!? ";
>
> And the output:
> ------------------------------------
> Warning: Invalid argument supplied for foreach() in
> /srv/home/u80959ue/public_html/scripts/common.php on line 28
> 33
> WTF?!?!?
>
> Fatal error: [] operator not supported for strings in
> /srv/home/u80959ue/public_html/scripts/common.php on line 169
> ---------------------------------------
>
> Indeed, the use of array(), once it starts misbehaving, wreaks havoc in
the
> local scope (possibly including the variable to which its result is
assigned).
>
> > Can you post the code in a .zip file or online somewhere?
>
> Unfortunately not.
>
> Szczepan Holyszewski
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Re: array() returns something weird
am 23.08.2009 00:34:06 von webmaster
> Hm. . .it does look odd. Searching the bugs database at
> http://bugs.php.net does turn up one other report (at
> http://bugs.php.net/bug.php?id=47870 ) of array() returning NULL in
> certain hard-to-duplicate circumstances on FreeBSD,
Yes, I found it even before posting here, but I wasn't sure whether to file a
new report or comment under this one. If your intuition is that these bugs are
related, then I will do the latter. Thank you for your attention.
> I don't suppose you have a development environment on another
> machine where you can test another version of PHP?
Assuming you mean a FreeBSD environment, nope :( but I will try on Linux
tomorrow.
Regards,
Szczepan Holyszewski
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Re: array() returns something weird
am 23.08.2009 01:14:32 von Lars Torben Wilson
2009/8/22 Szczepan HoÅyszewski :
>> Hm. . .it does look odd. Searching the bugs database at
>> http://bugs.php.net does turn up one other report (at
>> http://bugs.php.net/bug.php?id=3D47870 ) of array() returning NULL in
>> certain hard-to-duplicate circumstances on FreeBSD,
>
> Yes, I found it even before posting here, but I wasn't sure whether to fi=
le a
> new report or comment under this one. If your intuition is that these bug=
s are
> related, then I will do the latter. Thank you for your attention.
Well, the only things I'm basing my suspicion on are the nature of the
problem, the OS similarity and the fact that it seems to be difficult
to reproduce the problem reliably. The major problem with this guess
is that the original bug report does state that the bug did not show
up under 5.2.
>> I don't suppose you have a development environment on another
>> machine where you can test another version of PHP?
>
> Assuming you mean a FreeBSD environment, nope :( but I will try on Linux
> tomorrow.
OK. I do think (as I'm sure you know) that the best test would be in a
matching environment (since the result was reported to be different
under Linux for that bug), but of course that's not always realistic.
> Regards,
> Szczepan Holyszewski
I hope your problem can be resolved. If it does turn out to be a bug
in PHP I hope that will be enough to convince your host to upgrade.
Regards,
Torben
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
DOMNode children iteration (was Re: array() returns something weird)
New facts about the strange bug initially diagnosed as array() returning NU=
LL:
=46irstly, the issue is not really about array() returning null, but about =
full=20
blown UndefinedBehavior(TM) progressively trashing local variables. It just=
so=20
happened that I noticed it first with a variable to which array() had been=
=20
assigned just before things began breaking.
Secondly, I proudly present the culprit: things break when I iterate over a=
=20
DOMNode's children *by reference* using firstChild and nextSibling:
No problems if iteration is done by value or by DOMNodeList (childNodes,=20
DOMXPath...).
HOWEVER,
I still consider this a bug because it destablizes PHP. After the evil loop=
=20
has finished, things happen that should never happen, like a variable being=
=20
NULL immediately after being assigned array().
I attach a demonstration. It is a self-contained commented script that you =
can=20
execute from command line. Also attached is output on my machine.
/*
This program demonstrates mayhem caused by iterating over a DOMNode's children
using firstChild and nextSibling TAKEN BY REFERENCE.
It instantiates a DOMDocument, loads an XML fragment into it and processes it
three times - the good way, the mixed way (read below) and the evil way. Each time
recursion progress is logged and (trivial) transformation result is dumped
(if not errored out earlier).
* First time it takes a path in renderObject() that iterates over
child nodes using a DOMNodeList obtained with a DOMXPath query.
* Second time it uses DOMNodeList at the outermost level in renderObject()
but firstChild/nextSibling by reference at inner levels. This
demonstrates very nice trashing of local variables from which
transformation result is assembled in renderObject().
* Third time it always uses firstChild/nextSibling in renderObject().
On my machine it errors out at the outermost level but AFTER returning
from recursion.
*/
//The XML is formatted so that objects only contain params
//and no text or whitespace in between
$xmlfragment = <<
Some text.
Some more text
XMLFRAGMENT;
$doc = new DOMDocument("1.0", "utf-8"); $doc->loadXML($xmlfragment);
$root = $doc->childNodes->item(0);
//uncomment to display errors
//ini_set("display_errors", "On");
echo "THE GOOD WAY (DOMNodeList):\n\n";
echo "Recursion structure:\n\n";
$innerWay = GOOD_WAY;
$result=render($root, true);
echo "\nTransformation result:\n$result\n";
echo "Success!\n\n";
echo "THE MIXED WAY (DOMNodeList at outermost level, then firstChild/nextSibling by ref):\n\n";
echo "Recursion structure:\n\n";
$innerWay = EVIL_WAY;
$result=render($root, true);
echo "\nTransformation result:\n$result\n";
echo "Is it really a success?\n\n";
echo "THE EVIL WAY (firstChild/nextSibling by ref):\n\n";
echo "Recursion structure:\n\n";
$result=render($root, false);
echo "\nTransformation result:\n$result\n";
echo "Unexpected success!\n\n";
function render(&$node, $whichWay) {
$ret="";
//for each node
for($i=0; $i<$node->childNodes->length; ++$i) {
$child = $node->childNodes->item($i);
//if text node, append
if ($child instanceof DOMText) $ret .= $child->wholeText;
//if , render and append
else if ($child instanceof DOMElement && $child->tagName == "object")
Some text.
[object type='foo' name='bar'][param name='__default_content']
Some parameter text.
Some parameter text.
[object type='bar' name='nested'][param name='__default_content']
Some nested parameter text.
Some nested parameter text.
[object type='baz' name='deeply_nested'][param name='__default_content']
[/param][param name='bold']true[/param][/object]
More nested parameter text
More nested parameter text
[/param][/object]
[/param][/object]
Some more text
Success!
THE MIXED WAY (DOMNodeList at outermost level, then firstChild/nextSibling by ref):
Some text.
[object type='foo' name='bar'][param name='__default_content']
Some parameter text.
Some parameter text.
__default_content[param name='__default_content']__default_content[/param][/object]
[/param][/object]
Some more text
---------- Forwarded message ----------
From: Martin Scotta
Date: Tue, Aug 25, 2009 at 6:24 PM
Subject: Re: [PHP] DOMNode children iteration (was Re: array() returns
something weird)
To: webmaster@strefarytmu.pl
Fatal error: Call to a member function getAttribute() on a non-object in
testme.php on line *121*
I'm using a Apache/2.2.3 (Win32) PHP/5.2.6
Is the script correctly? I have removed the "&" in the loop and the script
returns the attached file.
It looks like a bogus bug?
2009/8/24 Szczepan HoÅyszewski
>
> Hi Lars and list!
>
> New facts about the strange bug initially diagnosed as array() returning
> NULL:
>
> Firstly, the issue is not really about array() returning null, but about
> full
> blown UndefinedBehavior(TM) progressively trashing local variables. It ju=
st
> so
> happened that I noticed it first with a variable to which array() had bee=
n
> assigned just before things began breaking.
>
> Secondly, I proudly present the culprit: things break when I iterate over=
a
> DOMNode's children *by reference* using firstChild and nextSibling:
>
> for($child=3D&$node->firstChild; $child; $child=3D&$child->nextSib=
ling)
> {
>
> //processing...
> }
>
> No problems if iteration is done by value or by DOMNodeList (childNodes,
> DOMXPath...).
>
> HOWEVER,
>
> I still consider this a bug because it destablizes PHP. After the evil lo=
op
> has finished, things happen that should never happen, like a variable bei=
ng
> NULL immediately after being assigned array().
>
> I attach a demonstration. It is a self-contained commented script that yo=
u
> can
> execute from command line. Also attached is output on my machine.
>
> Best regards,
> Szczepan HoÅyszewski
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
--0016e6460856e412430471fdf7e1--
Re: DOMNode children iteration (was Re: array() returns something weird)
am 26.08.2009 09:47:49 von webmaster
Martin Scotta wrote:
> Fatal error: Call to a member function getAttribute() on a non-object in
> testme.php on line *121*
Yes, this is _how_ the unmodified script errors out. It is not shown in the=
=20
output I attached in my previous message because display_errors is Off in m=
y=20
php.ini, and the line that sets it to On in my script is commented out.
> I'm using a Apache/2.2.3 (Win32) PHP/5.2.6
I am not using Apache at all. The same error can be seen when I run the scr=
ipt=20
directly through php on the command line.
> Is the script correctly? I have removed the "&" in the loop
I know that iterating a DOMNode's children using firstChild and nextSibling=
by=20
reference causes trouble, thank you. The problem is that it causes trouble=
=20
with objects unrelated to the loop itself, e.g. to variables defined _after=
_=20
the loop has terminated.
> and the script returns the attached file.
Do you mean it returns what is in the output file _I_ have attached, or did=
=20
_you_ try to attach something? If that is the case, then your attachment=20
didn't get through.
> It looks like a bogus bug?
I am certain it _is_ a genuine bug. For example, in PHP when you write:
$foo =3D array();
echo gettype($foo);
the output should not be NULL, but in my example script (unmodified, with=20
iteration by reference) things like this start happening at some point.
Regards,
Szczepan HoÅyszewski
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
RE: DOMNode children iteration (was Re: array() returns something weird)
> I really can't see why you'd want to use references in the posted
> loop anyway -- it's not likely to gain you any performance, and, as
> I understand it, may actually run more slowly than the
> non-reference version.
The why is irrelevant. It is perfectly legal PHP, and while it might be
illegal usage of DOMNode, it should only break the DOMNode, and not PHP
execution environment.
> I don't think it's possible to answer this for sure without seeing more of
> the code -- at least the complete body of the loop, plus as far as any
> further use of the variable $child (and any other variables assigned from
> it).
OK, I modified the example to show the problem _very_ directly. I commented out
the recursion-tracing echos, and added this code in renderObject() below the
if() that chooses between the good and evil loop, which means that the added
code is always executed immediately after the loop:
- are first defined at this point
- are initialized immediately
- are initialized with immediate data (empty array and two scalars), not
with results of prior computation
- are never used or changed except for being dumped
- don't get any references to them created
Therefore one must expect that var_dump will always dump this:
/*
This program demonstrates mayhem caused by iterating over a DOMNode's children
using firstChild and nextSibling TAKEN BY REFERENCE.
It instantiates a DOMDocument, loads an XML fragment into it and processes it
three times - the good way, the mixed way (read below) and the evil way. Each time
recursion progress is logged and (trivial) transformation result is dumped
(if not errored out earlier).
* First time it takes a path in renderObject() that iterates over
child nodes using a DOMNodeList obtained with a DOMXPath query.
* Second time it uses DOMNodeList at the outermost level in renderObject()
but firstChild/nextSibling by reference at inner levels. This
demonstrates very nice trashing of local variables from which
transformation result is assembled in renderObject().
* Third time it always uses firstChild/nextSibling in renderObject().
On my machine it errors out at the outermost level but AFTER returning
from recursion.
*/
//The XML is formatted so that objects only contain params
//and no text or whitespace in between
$xmlfragment = <<
Some text.
Some parameter text.
Some parameter text.
Some nested parameter text.
Some nested parameter text.
true
More nested parameter text
More nested parameter text
Some more text
XMLFRAGMENT;
$doc = new DOMDocument("1.0", "utf-8"); $doc->loadXML($xmlfragment);
$root = $doc->childNodes->item(0);
//uncomment to display errors
//ini_set("display_errors", "On");
echo "THE GOOD WAY (DOMNodeList):\n\n";
//echo "Recursion structure:\n\n";
$innerWay = GOOD_WAY;
$result=render($root, true);
echo "\nTransformation result:\n$result\n";
echo "Success!\n\n";
echo "THE MIXED WAY (DOMNodeList at outermost level, then firstChild/nextSibling by ref):\n\n";
//echo "Recursion structure:\n\n";
$innerWay = EVIL_WAY;
$result=render($root, true);
echo "\nTransformation result:\n$result\n";
echo "Is it really a success?\n\n";
echo "THE EVIL WAY (firstChild/nextSibling by ref):\n\n";
//echo "Recursion structure:\n\n";
$result=render($root, false);
echo "\nTransformation result:\n$result\n";
echo "Unexpected success!\n\n";
function render(&$node, $whichWay) {
$ret="";
//for each node
for($i=0; $i<$node->childNodes->length; ++$i) {
$child = $node->childNodes->item($i);
//if text node, append
if ($child instanceof DOMText) $ret .= $child->wholeText;
//if , render and append
else if ($child instanceof DOMElement && $child->tagName == "object") {